#!coding: utf-8
import sys 
import os
import os.path 

cur_path = os.path.dirname(__file__)
parent_path = os.path.abspath(os.path.join(cur_path, '..'))
sys.path.append(parent_path)

from gevent import server,pool,spawn,monkey
monkey.patch_all()

import json
import time 
import pymongo
import re 
import random

from topapi import *

import logging 
import logging.config

from render import generatePage
from itemsimilar import item_correl

logging.config.fileConfig('./conf/log.up2tb.conf')
tlog = logging.getLogger('root')

catsdata = json.load(open('invert.cat.json'))

def online_rec(mdb, item, items, catsdata):
    rec_iids = item_correl(catsdata, item, items, 'num_iid')
    ts = int(time.time())
    mdb.correl.save({'_id':item['num_iid'], 'rel':rec_iids, 'ts':ts})
    return rec_iids[:3]

def remove_re(flag):
    flag = '<a name="recommend_wgid_%s"></a>.*<a name="recommend_wgid_%s"></a>' %(flag, flag)
    repl = re.compile(flag, re.DOTALL)
    return repl.sub

def get_user(db, nick):
    u = db.user.find_one({'_id':nick})
    if not u:
        raise Exception('%s not in db' %(nick))
    return u

def item_remove(db, nick, num_iid, tbitem_obj, html_flag, fsub, session):
    tlog.debug('process update: nick=%s num_iid=%d' %(nick, num_iid))
    item_allinfo = tbitem_obj.get(session, num_iid, fields='desc')
    if 'desc' in item_allinfo:
        desc = item_allinfo['desc']
    else:
        raise Exception('desc not in [%s:%d] info getting from taobao' %(nick, num_iid))
    if html_flag not in desc:
        return
    desc = fsub(' ', desc)
    tbinfo = tbitem_obj.update(session, num_iid, desc=desc)
    tlog.debug('update [%s:%d] result: %s' %(nick, num_iid, repr(tbinfo)))

def batch_remove(db, nick):
    u = get_user(db, nick)
    allitems = Items().onsale(u['top_session'], fields='num_iid,title')
    tlog.debug('process update for nick=%s num=%d' %(nick, len(allitems)))
    tbitem = Item()
    temp = u['tg_temp']
    fsub = remove_re(temp['html_flag'])
    hisid = db.history.save({'nick':nick, 'm':2})
    suc, fail = 0, 0
    for item in allitems:
        num_iid = item['num_iid']
        title = item['title']
        try:
            item_remove(db, nick, num_iid, tbitem, temp['html_flag'], fsub, u['top_session'])
        except Exception as e:
            tlog.warning('item remove correl data of [%s:%d] fail: %s' %(nick, num_iid, repr(e)))
            db.hisdetail.save({'hisid':hisid, 'num_iid':num_iid, 'title':title, 'r':'失败'})
            fail += 1
            continue
        tlog.info('item remove correl data of [%s:%d] success' %(nick, num_iid))
        db.hisdetail.save({'hisid':hisid, 'num_iid':num_iid, 'title':title, 'r':'成功'})
        suc += 1
    db.history.update({'_id':hisid}, {'$set':{'suc':suc, 'fail':fail}})
    tlog.info('remove correl for %s success' %(nick))


def item_add(db, nick, item, tbitem_obj, html_flag, position, session, allitems):
    num_iid = item['num_iid']
    rec_iids = db.correl.find_one({'_id':num_iid})
    if not rec_iids:
        rec_iids = online_rec(db, item, allitems, catsdata)
        tlog.warning('not correl for [%d], use random' %(nick, num_iid))
    else:
        rec_iids = rec_iids['rel'][:3]
        tlog.debug('correl for [%d]: %s' %(num_iid, repr(rec_iids)))
    page = generatePage(db, nick, rec_iids) 
    page = '<a name="recommend_wgid_%s"></a>%s<a name="recommend_wgid_%s"></a>' %(
            html_flag, page.strip(), html_flag)
    item_allinfo = tbitem_obj.get(session, num_iid, fields='desc')
    if 'desc' in item_allinfo:
        desc = item_allinfo['desc']
    else:
        raise Exception('item info of [%s:%d] has not desc field' %(nick, num_iid))
    if position != 'b':
        desc = page + desc
    else:
        desc = desc + page
    tbinfo = tbitem_obj.update(session, num_iid, desc=desc)


def batch_add(db, nick):
    u = get_user(db, nick)
    allitems = Items().onsale(u['top_session'], fields='num_iid,title,cid')
    tbitem = Item()
    hisid = db.history.save({'nick':nick, 'm':1}) # use 1, stop 2
    suc, fail = 0, 0
    temp = u['tg_temp']
    for item in allitems:
        num_iid = item['num_iid']
        title = item['title']
        try:
            item_add(db, nick, item, tbitem, temp['html_flag'], temp['position'], u['top_session'], allitems)
        except Exception as e:
            tlog.warning('item add correl data to [%s:%d] fail: %s' %(nick, num_iid, repr(e)))
            db.hisdetail.save({'hisid':hisid, 'num_iid':num_iid, 'title':title, 'r':'失败'})
            fail += 1
            continue 
        tlog.info('item add correl data to [%s:%d] success' %(nick, num_iid))
        db.hisdetail.save({'hisid':hisid, 'num_iid':num_iid, 'title':title, 'r':'成功'})
        suc += 1
    db.history.update({'_id':hisid}, {'$set':{'suc':suc, 'fail':fail}})
    tlog.info('add correl for %s success' %(nick))

"""
recinfo = {'nick': nick, 'type': add | remove}
"""
def do_rec(recinfo):
    tlog.debug('do correl rec: %s' %(repr(recinfo)))
    m = pymongo.Connection(port=57324)
    db = m.taogold
    try:
        if recinfo['type'] == 'add':
            batch_add(db, recinfo['nick'])
        elif recinfo['type'] == 'remove':
            batch_remove(db, recinfo['nick'])
        else:
            tlog.warning('wrong type of recinfo: %s' %(repr(recinfo)))
    except Exception as e:
        tlog.warning('error in do_rec, recinfo=[%s]: %s' %(repr(recinfo), repr(e)))


def test_do_rec():
    recinfo = {'nick':'huiqing_shen', 'type':'add'}
    #recinfo = {'nick':'huiqing_shen', 'type':'remove'}
    do_rec(recinfo)


def srv_handle(socket, address):
    ct = socket.recv(1024)
    while not ct.endswith('\n\n'):
        ct += socket.recv(1024)
    try:
        recinfo = json.loads(ct)
    except Exception as e:
        tlog.warning('json load[%s] fail: %s' %(repr(ct), repr(e)))
        socket.send('fail\n\n')
        socket.close()
        return
    if 'type' not in recinfo or 'nick' not in recinfo:
        tlog.warning('wrong data: %s' %(repr(ct)))
        socket.send('fail\n\n')
    else:
        spawn(do_rec, recinfo)
        socket.send('success\n\n')
    socket.close()

def srv():
    srv = server.StreamServer(('127.0.0.1', 8600), srv_handle)
    srv.serve_forever()

def main():
    try:
        pid = os.fork() 
        if pid>0:
            sys.exit(0)
    except Exception as e:
        sys.exit('fork #1 error: %s' %(str(e)))
    try:
        pid = os.fork() 
        if pid>0: 
            sys.exit(0)
    except Exception as e:
        sys.exit('fork #2 error: %s' %(str(e)))
    srv()



if __name__ == '__main__':
    #test_do_rec()
    main()
